import abc
from typing import Generic, Optional, TypeVar

TagVal = TypeVar("TagVal")
TagQuery = TypeVar("TagQuery")
Matching = TypeVar("Matching")


class TagKey(Generic[TagVal, TagQuery, Matching], abc.ABC):
    @property
    @abc.abstractmethod
    def name(self) -> str:
        pass

    @property
    def default_val(self) -> Optional[TagVal]:
        """ Default value when this tag key is missing. """
        return None

    @abc.abstractmethod
    def match(self, query: Optional[TagQuery], val: Optional[TagVal]) -> Matching:
        pass

    def __str__(self):
        return self.name

    def __repr__(self):
        return f"<{self.__class__.__name__} {self.name}>"
